<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <script>
    /* 
      1. 发布者（Publisher）：负责发布事件。当某个事件发生时，发布者将通知所有订阅了该事件的订阅者。
      2. 订阅者（Subscriber）：订阅感兴趣的事件，并在事件发生时接收通知。
      3. 事件中心（Event Center）：维护事件和订阅者之间的关系，负责将事件分发给订阅者。 
      多对多
      观察者模式一对多
    */

   /*  发布-订阅者模式（Publish-Subscribe Pattern）在项目中可以用于以下几个方面： */

    /* 1. 事件系统：发布-订阅者模式可以用于实现事件系统，用于组件之间的通信。当一个组件触发了某个事件，其他订阅了该事件的组件可以接收到通知并执行相应的操作。这种模式可以解耦组件之间的依赖关系，提高代码的可维护性和扩展性。

    2. 消息队列：发布-订阅者模式可以用于实现消息队列，用于处理异步任务。当一个任务完成时，可以将结果发布到消息队列中，其他订阅了该消息的任务可以接收到通知并进行相应的处理。这种模式可以提高系统的并发性和响应性。

    3. 状态管理：发布-订阅者模式可以用于实现状态管理，用于管理应用程序的状态。当状态发生变化时，可以发布状态更新的事件，其他订阅了该事件的组件可以接收到通知并更新自己的状态。这种模式可以简化状态管理的逻辑，提高代码的可读性和可维护性。

    4. 消息通知：发布-订阅者模式可以用于实现消息通知，用于向用户发送通知消息。当有新的消息需要通知用户时，可以发布通知事件，其他订阅了该事件的用户可以接收到通知并查看消息内容。这种模式可以提高用户体验，增强系统的交互性。
 */
    this.events = {
      eventName: [cb1,cb2]  
    } //发布，调用事件中心对应函数，遍历以此执行函数(eventName, ...args)

    //订阅，向事件中心添加事件[cb1,cb2,cb3](eventName,callback)
    //取消订阅 取消cb2 [cb1](eventName, callback)
    // 这样看起来，订阅是在注册事件， 发布是在掉用注册的事件， 可以参考 emitter 库， vue 中学过
    class EventEmitter {
      constructor(){
        this.events = {} // 事件中心, key(事件名): cb[]（回调函数）
      }
      publish(eventName, ...args){ // 发布，调用事件中心中对应的函数
        if(this.events[eventName]){
          this.events[eventName].forEach((cb) => cb.apply(this,args))
        }
      }
      subscribe(eventName, callback){ // 订阅，向事件中心添加事件
        if(this.events[eventName]){
          this.events[eventName].push(callback)
        } else {
          this.events[eventName] = [callback]
        }
      }
      unSubscribe(eventName, callback){ // 取消订阅， 删除事件中心对应回调函数
        if(this.events[eventName]){
          this.events[eventName] = this.events[eventName].filter((cb) => cb !== callback)
        }
      }
    }
  </script>
</body>
</html>
